home *** CD-ROM | disk | FTP | other *** search
- /*
- * Design Patterns Examples
- * © 1997 John Schettino, js12@gte.com
- *
- */
-
- #include "Patterns.h"
- #include <iostream.h>
-
- // This example uses the IterateDirectory() function from MoreFiles 1.4.3
- // This Apple - supplied code is available from
- // ftp://ftpdev.info.apple.com/Developer_Services/Sample_Code/MoreFiles_1.4.3/
- #include "IterateDirectory.h"
-
- // -- Binary Tree Node member fns --
-
-
- ostream&
- operator<< (ostream& os, const TreeNodePtr& t)
- {
- os << *t; return os;
- }
-
- ostream&
- operator<< (ostream& os, TreeNode& t)
- {
- os << "[" << t.output() << "]\n";
- return os;
- }
-
-
- // -- DFTreeNodeIterator member fns --
-
- DFTreeNodeIterator::DFTreeNodeIterator(BinaryTreeNode &tree)
- {
- _origTree = _tree = &tree;
- _pushLeft();
- }
-
- // follow left branch pushing nodes onto stack
- // done for every first-time visit
-
- void
- DFTreeNodeIterator::_pushLeft()
- {
- while (_tree->leftChild())
- {
- _pendingNodes.push(_tree);
- _tree = _tree->leftChild();
- }
- }
-
- // postfix ++
-
- TreeNodePtr
- DFTreeNodeIterator::operator++ (int)
- {
- TreeNode* theNode = current();
- next();
- return theNode;
- }
-
- TreeNodePtr
- DFTreeNodeIterator::current ()
- {
- return _tree;
- }
-
- // this is the prefix ++ operator
- TreeNodePtr
- DFTreeNodeIterator::next()
- {
- if (_tree)
- {
- // follow right child ptr
- if (_tree->rightChild())
- {
- _tree = _tree->rightChild();
- _pushLeft();
- }
- else if (_pendingNodes.size() > 0)
- { // end of a branch, pop up and return node itself
- _tree = _pendingNodes.top();
- _pendingNodes.pop();
- }
- else
- _tree = 0; // all done
- }
- return _tree;
- }
-
- // reset the iterator to the first node
- void
- DFTreeNodeIterator::reset()
- {
- _tree = _origTree;
- _pushLeft();
- }
-
- // -- BFTreeNodeIterator member fns --
-
- BFTreeNodeIterator::BFTreeNodeIterator(BinaryTreeNode &tree)
- {
- _origTree = _tree = &tree;
- _current = IO_node;
- }
-
- TreeNodePtr
- BFTreeNodeIterator::operator++ (int)
- {
- TreeNode* theNode = current();
- next();
- return theNode;
- }
-
- // this is the * operator
- TreeNodePtr
- BFTreeNodeIterator::current ()
- {
- if (!_tree) return 0;
-
- switch (_current) {
- case IO_node:
- return _tree;
- case IO_left:
- return _tree->leftChild();
- case IO_right:
- return _tree->rightChild();
- }
-
- }
-
- // this is the prefix ++ operator
- TreeNodePtr
- BFTreeNodeIterator::next()
- {
- BinaryTreeNodePtr c;
- switch (_current) {
- case IO_node:
- if (_tree->leftChild()) _current = IO_left;
- else if (_tree->rightChild()) _current = IO_right;
- else if (_pendingNodes.size() > 0)
- {
- _tree = _pendingNodes.front();
- _pendingNodes.pop();
- _current = _tree->leftChild() ? IO_left : IO_right;
- }
- else _tree = 0;
- return current();
- case IO_left:
- c = (BinaryTreeNodePtr) current();
- if (c->leftChild() || c->rightChild()) _pendingNodes.push(c);
- if (_tree->rightChild()) _current = IO_right;
- else if (_pendingNodes.size() > 0)
- {
- _tree = _pendingNodes.front();
- _pendingNodes.pop();
- _current = _tree->leftChild() ? IO_left : IO_right;
- }
- else _tree = 0;
- return current();
- case IO_right:
- c = (BinaryTreeNodePtr) current();
- if (c->leftChild() || c->rightChild()) _pendingNodes.push(c);
- if (_pendingNodes.size() > 0)
- {
- _tree = _pendingNodes.front();
- _pendingNodes.pop();
- _current = _tree->leftChild() ? IO_left : IO_right;
- }
- else _tree = 0;
- return current();
- }
- }
-
- // reset the iterator to the first node
- void
- BFTreeNodeIterator::reset()
- {
- _tree = _origTree;
- _current = IO_node;
- }
-
-
- // -- BinaryTreeBuilder member fns --
-
- BinaryTreeBuilder::BinaryTreeBuilder()
- {
- _currentBTree = 0;
- }
-
- TreeNodePtr
- BinaryTreeBuilder::GetTree()
- {
- return _currentBTree;
- }
-
- void
- BinaryTreeBuilder::AddNode(TreeNode* theNode)
- {
- BinaryTreeNodePtr testNode = (BinaryTreeNodePtr) _currentBTree;
- if (!testNode) _currentBTree = theNode;
- else
- {
- for (;;)
- {
- if (((BinaryTreeNodePtr)theNode)->compare(*testNode) <0)
- {
- if (testNode->leftChild()) testNode = testNode->leftChild();
- else
- {
- testNode->setLeftChild((BinaryTreeNodePtr)theNode);
- return;
- }
- }
- else
- {
- if (testNode->rightChild()) testNode = testNode->rightChild();
- else
- {
- testNode->setRightChild((BinaryTreeNodePtr)theNode);
- return;
- }
- }
- }
- }
- }
-
- // -- HBTreeBuilder member fns --
-
- HBTreeBuilder::HBTreeBuilder()
- {
- _currentBTree = 0;
- }
-
- TreeNodePtr
- HBTreeBuilder::GetTree()
- {
- return _currentBTree;
- }
-
- void
- HBTreeBuilder::AddNode(TreeNode* theNode)
- {
- BinaryTreeNodePtr testNode = (BinaryTreeNodePtr) _currentBTree;
- if (!testNode) _currentBTree = theNode;
- else
- {
- BinaryTreeNodePtr grandparent = 0, parent = 0;
- for (;;)
- {
- if (((BinaryTreeNodePtr)theNode)->compare(*testNode) <0)
- {
- if (testNode->leftChild())
- {
- grandparent = parent;
- parent = testNode;
- testNode = testNode->leftChild();
- }
- else
- {
- // try to ballance a tree that has a long left chain
- if (parent && grandparent &&
- !(parent->rightChild()) && !(testNode->rightChild()))
- {
- if (parent->compare(*grandparent) <0) grandparent->setLeftChild(testNode);
- else grandparent->setRightChild(testNode);
- parent->setLeftChild(0);
- testNode->setRightChild(parent);
- }
- testNode->setLeftChild((BinaryTreeNodePtr)theNode);
- return;
- }
- }
- else
- {
- if (testNode->rightChild())
- {
- grandparent = parent;
- parent = testNode;
- testNode = testNode->rightChild();
- }
- else
- {
- // try to ballance a tree that has a long right chain
- if (parent && grandparent &&
- !(parent->leftChild()) && !(testNode->leftChild()))
- {
- if (parent->compare(*grandparent) <0) grandparent->setLeftChild(testNode);
- else grandparent->setRightChild(testNode);
- parent->setRightChild(0);
- testNode->setLeftChild(parent);
- }
- testNode->setRightChild((BinaryTreeNodePtr)theNode);
- return;
- }
- }
- }
- }
- }
-
-
- // -- callback for IterateDirectory() --
- // adds name of each file as a node in the tree
- // tree builder passed in tbuilder variable
-
- pascal
- void
- getName(const CInfoPBRec * const cpbPtr,
- Boolean *quitFlag,
- void *tbuilder)
- {
- char *cstr = p2cstr(cpbPtr->hFileInfo.ioNamePtr);
- ((TreeBuilder *)tbuilder)->AddNode(new BinaryTreeNode(cstr));
- }
-
- // -- walk a tree using the TreeNodeIterator
- // use the current/next member functions
-
- void walkTree1(TreeNodeIterator &treeNodes)
- {
- cout <<
- "* Fetching nodes via current/next operators\n";
-
- for ( ;treeNodes.current(); treeNodes.next())
- cout << treeNodes.current();
- }
-
- // -- walk a tree using the TreeNodeIterator
- // use the ++ operator
-
- void walkTree2(TreeNodeIterator &treeNodes)
- {
- cout << "* Fetching nodes via ++ operator\n";
-
- while (TreeNodePtr p = treeNodes++)
- cout << p;
-
- }
-
- // -- main program allocates two treeBuilders,
- // calls IterateDirectory() on a test directory to
- // populate the trees, and the creates several different
- // iterators and "walks" the trees.
-
- void main(void)
- {
- cout << "Building binary tree\n";
-
- BinaryTreeBuilder b;
-
- // iterate over a directory named Example Dir
- // within the program's current working directory
- StringPtr dir = c2pstr(":Example Dir");
-
- IterateDirectory(0,0,dir,2,getName, &b);
- TreeNodePtr myTree = (BinaryTreeNodePtr) b.GetTree();
-
- cout << "The nodes, using a depth-first iterator:\n";
-
- DFTreeNodeIterator depthFirst(*(BinaryTreeNodePtr)myTree);
- walkTree1(depthFirst);
-
- cout << "\nThe nodes, same iterator, alternate API:\n";
-
- depthFirst.reset();
- walkTree2(depthFirst);
-
- cout << "\nThe nodes, using a bredth-first iterator:\n";
-
- BFTreeNodeIterator bredthFirst(*(BinaryTreeNodePtr)myTree);
- walkTree2(bredthFirst);
-
- cout << "\nBuilding height balanced binary tree\n";
-
- HBTreeBuilder hb;
-
- IterateDirectory(0,0,dir,2, getName, &hb);
- myTree = (BinaryTreeNodePtr) hb.GetTree();
-
- cout << "The HB nodes, using a depth-first iterator:\n";
-
- DFTreeNodeIterator depthFirstHB(*(BinaryTreeNodePtr)myTree);
- walkTree2(depthFirstHB);
-
- cout << "\nThe HB nodes, using a BF iterator:\n";
-
- BFTreeNodeIterator bredthFirstHB(*(BinaryTreeNodePtr)myTree);
- walkTree2(bredthFirstHB);
-
- cout << "\nDone\n";
- }
-
-
-